﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;

class EverythingHelper
{
    const string everything_process_name = "Everything";
    const int bufsize = 260;

    #region EverythingDllImport
    const int EVERYTHING_OK = 0;
    const int EVERYTHING_ERROR_MEMORY = 1;
    const int EVERYTHING_ERROR_IPC = 2;
    const int EVERYTHING_ERROR_REGISTERCLASSEX = 3;
    const int EVERYTHING_ERROR_CREATEWINDOW = 4;
    const int EVERYTHING_ERROR_CREATETHREAD = 5;
    const int EVERYTHING_ERROR_INVALIDINDEX = 6;
    const int EVERYTHING_ERROR_INVALIDCALL = 7;

    [DllImport("Everything32.dll", CharSet = CharSet.Unicode)]
    public static extern int Everything_SetSearchW(string lpSearchString);
    [DllImport("Everything32.dll")]
    public static extern void Everything_SetMatchPath(bool bEnable);
    [DllImport("Everything32.dll")]
    public static extern void Everything_SetMatchCase(bool bEnable);
    [DllImport("Everything32.dll")]
    public static extern void Everything_SetMatchWholeWord(bool bEnable);
    [DllImport("Everything32.dll")]
    public static extern void Everything_SetRegex(bool bEnable);
    [DllImport("Everything32.dll")]
    public static extern void Everything_SetMax(int dwMax);
    [DllImport("Everything32.dll")]
    public static extern void Everything_SetOffset(int dwOffset);

    [DllImport("Everything32.dll")]
    public static extern bool Everything_GetMatchPath();
    [DllImport("Everything32.dll")]
    public static extern bool Everything_GetMatchCase();
    [DllImport("Everything32.dll")]
    public static extern bool Everything_GetMatchWholeWord();
    [DllImport("Everything32.dll")]
    public static extern bool Everything_GetRegex();
    [DllImport("Everything32.dll")]
    public static extern UInt32 Everything_GetMax();
    [DllImport("Everything32.dll")]
    public static extern UInt32 Everything_GetOffset();
    [DllImport("Everything32.dll")]
    public static extern string Everything_GetSearchW();
    [DllImport("Everything32.dll")]
    public static extern int Everything_GetLastError();

    [DllImport("Everything32.dll")]
    public static extern bool Everything_QueryW(bool bWait);

    [DllImport("Everything32.dll")]
    public static extern void Everything_SortResultsByPath();

    [DllImport("Everything32.dll")]
    public static extern int Everything_GetNumFileResults();
    [DllImport("Everything32.dll")]
    public static extern int Everything_GetNumFolderResults();
    [DllImport("Everything32.dll")]
    public static extern int Everything_GetNumResults();
    [DllImport("Everything32.dll")]
    public static extern int Everything_GetTotFileResults();
    [DllImport("Everything32.dll")]
    public static extern int Everything_GetTotFolderResults();
    [DllImport("Everything32.dll")]
    public static extern int Everything_GetTotResults();
    [DllImport("Everything32.dll")]
    public static extern bool Everything_IsVolumeResult(int nIndex);
    [DllImport("Everything32.dll")]
    public static extern bool Everything_IsFolderResult(int nIndex);
    [DllImport("Everything32.dll")]
    public static extern bool Everything_IsFileResult(int nIndex);
    [DllImport("Everything32.dll", CharSet = CharSet.Unicode)]
    public static extern void Everything_GetResultFullPathNameW(int nIndex, StringBuilder lpString, int nMaxCount);
    [DllImport("Everything32.dll")]
    public static extern void Everything_Reset();
    #endregion

    public static List<string> StartEverythingSearch(string searchStr, string path_everything)
    {
        //如果指定everything还没有打开，则先打开everything
        if (!ExplorerUtil.IsTheProcessOnRunning(everything_process_name))
        {
            if (File.Exists(path_everything))
            {
                Process.Start(path_everything);
            }
            else
            {
                MessageBox.Show("没有找到everything程序！");
                return null;
            }
        }

        //等待程序启动完成
        Thread.Sleep(2000);

        List<string> final_results = new List<string>();
        StringBuilder buf = new StringBuilder(bufsize);

        StartSearch(searchStr);

        int lastResultsCount = 0;
        int resultsCount = -1;
        resultsCount = Everything_GetNumResults();
        //检测everything是否完全启动，完全启动后才往下面运行
        while (resultsCount <= 0)
        {
            Thread.Sleep(10);
            StartSearch(searchStr);
            resultsCount = Everything_GetNumResults();
        }

        //不断查询结果，直到查到的结果总数不变，即everything已经扫描完了所有的路径
        while (lastResultsCount != resultsCount)
        {
            lastResultsCount = resultsCount;
            Thread.Sleep(500);
            StartSearch(searchStr);
            resultsCount = Everything_GetNumResults();
        }

        //查询完成
        for (int i = 0; i < resultsCount; i++)
        {
            Everything_GetResultFullPathNameW(i, buf, bufsize);
            final_results.Add(buf.ToString());
        }

        return final_results;

    }

    private static void StartSearch(string searchStr)
    {
        Everything_SetSearchW(searchStr);
        Everything_QueryW(true);
    }

}
